home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1993 / MacHack 1993.toast / MacHack™ 1987-1992 / MacHack™ '90 / Other Stuff / Demos ƒ / TOPS SoftTalk Package / STServer ƒ / STServer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-08  |  23.2 KB  |  736 lines  |  [TEXT/MPS ]

  1. /*
  2. ------------------------------------------------------------------------------
  3. |    Sun Microsystems, TOPS Division
  4. |    950 Marina Village Parkway
  5. |    P.O. Box 4016
  6. |    Alameda, CA 94501
  7. |    
  8. |    Copyright (c) 1989 Sun Microsystems, Inc. All rights reserved.
  9. |    
  10. |    Sun considers its source code as an unpublished, proprietary trade secret,
  11. |    and it is available only under strict license provisions. This copyright
  12. |    notice is placed here only to protect Sun in the event the source is deemed
  13. |    a published work. Disassembly, decompilation, or other means of reducing the
  14. |    object code to human readable form is prohibited by the license agreement
  15. |    under which this code is provided to the user or company in possession of
  16. |    this copy.
  17. |    
  18. |    RESTRICTED RIGHTS LEGEND: Use, duplication, or disclosure by the Government
  19. |    is subject to restrictions as set forth in subparagraph (c) (1) (ii) of the
  20. |    Rights in Technical Data and Computer Software clause at DFARS 52.227-7013
  21. |    and in similar clauses in the FAR and NASA FAR supplement.
  22. ------------------------------------------------------------------------------
  23. */
  24.  
  25.  
  26.  
  27. /*
  28. ================================================================================
  29. **
  30. **    PROJECT:    SoftTalk
  31. **
  32. **    FILE:        STServer.c
  33. **
  34. **    Purpose:
  35. **        This file is an example of how to write a SoftTalk server.  It demonstrates how
  36. **        to create a server entity, how to export your functions by registering them with
  37. **        SoftTalk, and how to convert SoftTalk's register-based calling conventions into
  38. **        standard C function calls.  Furthermore, it demonstrates how to ensure that you
  39. **        have access to your globals when your service routines are called at interrupt-time.
  40. **
  41. **    ----------------------------------------------------------------------------
  42. **
  43. **    Version        Date        Author        Description
  44. **    -------        ----        ------        -----------
  45. **    1.0.2        30-Aug-89     MAC            Second draft. Added Func6, SampleStruct.
  46. **    1.0.1        17-Aug-89     MAC            First draft.
  47. **
  48. ================================================================================
  49. */
  50.  
  51.  
  52.  
  53. /*
  54. **------------------------------------------------------------------------------
  55. **        INCLUDES
  56. **------------------------------------------------------------------------------
  57. */
  58. #include "STServer.h"
  59. #include <MacTypes.h>
  60. #include "SoftTalk.h"
  61. #include "CSTServerApp.h"
  62. #include <pascal.h>
  63. #include "InterruptEnv.h"
  64.  
  65.  
  66. /*
  67. **------------------------------------------------------------------------------
  68. **        CONST
  69. **------------------------------------------------------------------------------
  70. */
  71. #define kFunctionRank (kSystemTaskRank)
  72.     /* we want to be called with lower priority than at SystemTask() time */
  73.  
  74.  
  75.  
  76. /*
  77. **------------------------------------------------------------------------------
  78. **        GLOBAL VARS
  79. **------------------------------------------------------------------------------
  80. */
  81. extern CSTServerApp* gApp; /* only so we can print information */
  82.  
  83. static STServer gServerID = 0;        /* the id of the server entity we create */
  84.  
  85. static INT32 gFunc1Count = 0;            /* count how many times func1() has been called */
  86. static INT32 gFunc2Count = 0;            /* count how many times func2() has been called */
  87. static INT32 gFunc3Count = 0;            /* count how many times func3() has been called */
  88. static INT32 gFunc4Count = 0;            /* count how many times func4() has been called */
  89. static INT32 gFunc5Count = 0;            /* count how many times func5() has been called */
  90.  
  91.  
  92.  
  93.  
  94. /*
  95. **------------------------------------------------------------------------------
  96. **        PROTOTYPES
  97. **------------------------------------------------------------------------------
  98. */
  99. extern pascal void NumToString(long, Str255); /* for WriteLn purposes */
  100. static INT32 _AcceptSession(void);    /* Glue from SoftTalk/Consulair to Lightspeed */
  101. static INT32 _Func1(void);                    /* Glue from SoftTalk/Consulair to Lightspeed */
  102. static INT32 _Func2(void);                    /* Glue from SoftTalk/Consulair to Lightspeed */
  103. static INT32 _Func3(void);                    /* Glue from SoftTalk/Consulair to Lightspeed */
  104. static INT32 _Func4(void);                    /* Glue from SoftTalk/Consulair to Lightspeed */
  105. static INT32 _Func5(void);                    /* Glue from SoftTalk/Consulair to Lightspeed */
  106. static INT32 AcceptSession(STSession sessionID);
  107.  
  108. static INT32 SetupInterruptEnv(void);    /* setup interrupt-level environment */
  109. static void ExitInterruptEnv(INT32 value);        /* clean-up from interrupt-level environment */
  110.  
  111.  
  112.  
  113.  
  114. /*
  115. **    ----------------------------------------------------------------------------
  116. **    FUNCTION SetupInterruptEnv() => INT32: setup interrupt-level environment
  117. **    ----------------------------------------------------------------------------
  118. **
  119. **    Purpose:
  120. **        Create an interrupt-level environment that allows access to globals.
  121. **        Return the value of A5 that points to our globals.
  122. **
  123. **    Usage:
  124. **        Call at the beginning of an interrupt-level function that wishes to
  125. **        access globals.  The calling routine should save the value returned
  126. **        by SetupInterruptEnv and hand it to ExitInterruptEnv when that is called.
  127. **
  128. **    ----------------------------------------------------------------------------
  129. **    Version        Date        Author        Description
  130. **    -------        ----        ------        -----------
  131. **    01a             8/17/89     MAC            First draft.
  132. **    ----------------------------------------------------------------------------
  133. */
  134. static INT32 SetupInterruptEnv(void) {
  135.     return SetA5(GetMyRealA5());    /* return the desired A5 */
  136. }
  137.  
  138.  
  139. /*
  140. **    ----------------------------------------------------------------------------
  141. **    FUNCTION ExitInterruptEnv() : clean-up from interrupt-level environment
  142. **    ----------------------------------------------------------------------------
  143. **
  144. **    Purpose:
  145. **        restore the environment we found before we setup our interrupt-level
  146. **        environment.  Reset A5 to its value on entry to the interrupt routine.
  147. **
  148. **    Usage:
  149. **        Call at the end of an interrupt-level routine that called SetupInterruptEnv().
  150. **        The argument "value" should be what SetupInterruptEnv returned.
  151. **
  152. **    ----------------------------------------------------------------------------
  153. **    Version        Date        Author        Description
  154. **    -------        ----        ------        -----------
  155. **    01a             8/17/89     MAC            First draft.
  156. **    ----------------------------------------------------------------------------
  157. */
  158. static void ExitInterruptEnv(INT32 environValue){
  159.     (void) SetA5(environValue); /* restore the A5 we found on entry */
  160. }
  161.  
  162.  
  163.  
  164.  
  165.  
  166. /*
  167. **    ----------------------------------------------------------------------------
  168. **    FUNCTION AcceptSession() => INT32 : can we accept another session?
  169. **    ----------------------------------------------------------------------------
  170. **
  171. **    Purpose:
  172. **        Tell SoftTalk whether our server is willing to accept another client.  This
  173. **        service routine is required for every server.  Our version simply returns TRUE
  174. **        indicating that we can accept another client.  A real server would base its decision
  175. **        on available server resources, etc.
  176. **
  177. **    Usage:
  178. **        Since SoftTalk calls service routines with args in registers, we have some asm glue
  179. **        to transfer args onto the stack; we then execute a standard C function call.
  180. **        This asm glue routine is registered with SoftTalk, and will then be called by
  181. **        SoftTalk (at interrupt time) whenever a new session is requested.
  182. **
  183. **    ----------------------------------------------------------------------------
  184. **    Version        Date        Author        Description
  185. **    -------        ----        ------        -----------
  186. **    01a             8/17/89     MAC            First draft.
  187. **    ----------------------------------------------------------------------------
  188. */
  189.  
  190. static INT32 _AcceptSession(void) {
  191.     asm    {
  192.         move.l    d0,-(sp)            /* move the arg "STSession sessionID" onto the stack */
  193.         jsr        AcceptSession        /* call the C function */
  194.         add.l    #4,sp                        /* clean up the stack */
  195.         }
  196. }
  197.  
  198.  
  199. static INT32 AcceptSession(STSession sessionID) {
  200.     Str255 msg;                    /* message string */
  201.     INT32 environValue;    /* interrupt environment pointer */
  202.     
  203.     /* we're at interrupt level */
  204.     environValue = SetupInterruptEnv();
  205.  
  206.     gApp->Msg((unsigned char*)"\pAcceptSession:  sessionID = ");
  207.     NumToString((long)sessionID,msg);
  208.     gApp->Msg(msg);
  209.     gApp->NewLine();
  210.  
  211.     ExitInterruptEnv(environValue);
  212.     return(noErr);
  213. }
  214.  
  215.  
  216.  
  217.  
  218. /*
  219. **    ----------------------------------------------------------------------------
  220. **    FUNCTION Func1() => INT32 : sample service routine
  221. **    ----------------------------------------------------------------------------
  222. **
  223. **    Purpose:
  224. **        Example of a service routine that accepts no args.  The return value is the number
  225. **        of times this routine has been executed (saved in the global gFunc1Count).
  226. **
  227. **    Usage:
  228. **        Since SoftTalk calls service routines with args in registers, we have some asm glue
  229. **        to transfer args onto the stack; we then execute a standard C function call.
  230. **        This asm glue routine is registered with SoftTalk, and will then be called by
  231. **        SoftTalk (at interrupt time) whenever a new session is requested.
  232. **
  233. **    ----------------------------------------------------------------------------
  234. **    Version        Date        Author        Description
  235. **    -------        ----        ------        -----------
  236. **    01a             8/17/89     MAC            First draft.
  237. **    ----------------------------------------------------------------------------
  238. */
  239.  
  240. static INT32 _Func1(void) {
  241.     asm    {
  242.         jsr        Func1        /* call the C function */
  243.         }
  244. }
  245.  
  246. INT32 Func1(void) {
  247.     INT32 environValue;    /* interrupt environment pointer */
  248.     INT32 returnValue;
  249.     
  250.     /* we're at interrupt level */
  251.     environValue = SetupInterruptEnv();
  252.  
  253.     returnValue = gFunc1Count++;
  254.     gApp->Msg((unsigned char*)"\p==> Function1");
  255.     gApp->NewLine();
  256.     gApp->NewLine();
  257.  
  258.     ExitInterruptEnv(environValue);
  259.     return(returnValue);
  260. }
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267. /*
  268. **    ----------------------------------------------------------------------------
  269. **    FUNCTION Func2() => INT32 : sample service routine
  270. **    ----------------------------------------------------------------------------
  271. **
  272. **    Purpose:
  273. **        Example of a service routine that accepts one INT32 arg.  The return value is the number
  274. **        of times this routine has been executed (saved in the global gFunc2Count).
  275. **
  276. **    Usage:
  277. **        Since SoftTalk calls service routines with args in registers, we have some asm glue
  278. **        to transfer args onto the stack; we then execute a standard C function call.
  279. **        This asm glue routine is registered with SoftTalk, and will then be called by
  280. **        SoftTalk (at interrupt time) whenever a new session is requested.
  281. **
  282. **    ----------------------------------------------------------------------------
  283. **    Version        Date        Author        Description
  284. **    -------        ----        ------        -----------
  285. **    01a             8/17/89     MAC            First draft.
  286. **    ----------------------------------------------------------------------------
  287. */
  288.  
  289. static INT32 _Func2(void) {
  290.     asm    {
  291.         move.l    d0,-(sp)    /* move the arg "INT32 arg1" onto the stack */
  292.                                             /* NOTE: since its an INT32 we do a "move.l" */
  293.  
  294.         jsr        Func2                /* call the C function */
  295.  
  296.         add.l    #4,sp                /* clean up the stack: add sizeof(INT32) to SP  */
  297.         }
  298. }
  299.  
  300. INT32 Func2(INT32 arg1) {
  301.     Str255 msg;                    /* message string */
  302.     INT32 environValue;    /* interrupt environment pointer */
  303.     INT32 returnValue;
  304.     
  305.     /* we're at interrupt level */
  306.     environValue = SetupInterruptEnv();
  307.  
  308.     returnValue = gFunc2Count++;    
  309.     gApp->Msg((unsigned char*)"\p==> Function2:  arg1 = ");
  310.     NumToString((long)arg1,msg);
  311.     gApp->Msg(msg);
  312.     gApp->NewLine();
  313.     gApp->NewLine();
  314.  
  315.     ExitInterruptEnv(environValue);
  316.     return(returnValue);
  317. }
  318.  
  319.  
  320.  
  321.  
  322.  
  323.  
  324. /*
  325. **    ----------------------------------------------------------------------------
  326. **    FUNCTION Func3() => INT32 : sample service routine
  327. **    ----------------------------------------------------------------------------
  328. **
  329. **    Purpose:
  330. **        Example of a service routine that accepts two args.  The return value is the number
  331. **        of times this routine has been executed (saved in the global gFunc3Count).
  332. **
  333. **    Usage:
  334. **        Since SoftTalk calls service routines with args in registers, we have some asm glue
  335. **        to transfer args onto the stack; we then execute a standard C function call.
  336. **        This asm glue routine is registered with SoftTalk, and will then be called by
  337. **        SoftTalk (at interrupt time) whenever a new session is requested.
  338. **
  339. **    ----------------------------------------------------------------------------
  340. **    Version        Date        Author        Description
  341. **    -------        ----        ------        -----------
  342. **    01a             8/17/89     MAC            First draft.
  343. **    ----------------------------------------------------------------------------
  344. */
  345.  
  346. static INT32 _Func3(void) {
  347.     asm    {
  348.         move.w    d1,-(sp)    /* move the arg "INT16 arg2" onto the stack */
  349.                                             /* NOTE: since its an INT16 we do a "move.w" */
  350.  
  351.         move.l    d0,-(sp)    /* move the arg "INT32 arg1" onto the stack */
  352.                                             /* NOTE: since its an INT32 we do a "move.l" */
  353.  
  354.         jsr        Func3                /* call the C function */
  355.  
  356.         add.l    #6,sp                /* clean up the stack: add sizeof(INT16) and sizeof(INT32) to SP */
  357.         }
  358. }
  359.  
  360. INT32 Func3(INT32 arg1, INT16 arg2) {
  361.     Str255 msg;                    /* message string */
  362.     INT32 environValue;    /* interrupt environment pointer */
  363.     INT32 returnValue;
  364.     
  365.     /* we're at interrupt level */
  366.     environValue = SetupInterruptEnv();
  367.  
  368.     returnValue = gFunc3Count++;        
  369.     gApp->Msg((unsigned char*)"\p==> Function3:  arg1 = ");
  370.     NumToString((long)arg1,msg);
  371.     gApp->Msg(msg);
  372.     gApp->Msg((unsigned char*)"\p                arg2 = ");
  373.     NumToString((long)arg2,msg);
  374.     gApp->Msg(msg);
  375.     gApp->NewLine();
  376.     gApp->NewLine();
  377.  
  378.     ExitInterruptEnv(environValue);
  379.     return(returnValue);
  380. }
  381.  
  382.  
  383.  
  384.  
  385.  
  386.  
  387. /*
  388. **    ----------------------------------------------------------------------------
  389. **    FUNCTION Func4() => INT32 : sample service routine
  390. **    ----------------------------------------------------------------------------
  391. **
  392. **    Purpose:
  393. **        Example of a service routine that accepts one C-string arg.  The return value is the number
  394. **        of times this routine has been executed (saved in the global gFunc4Count).
  395. **
  396. **    Usage:
  397. **        Since SoftTalk calls service routines with args in registers, we have some asm glue
  398. **        to transfer args onto the stack; we then execute a standard C function call.
  399. **        This asm glue routine is registered with SoftTalk, and will then be called by
  400. **        SoftTalk (at interrupt time) whenever a new session is requested.
  401. **
  402. **    ----------------------------------------------------------------------------
  403. **    Version        Date        Author        Description
  404. **    -------        ----        ------        -----------
  405. **    01a             8/17/89     MAC            First draft.
  406. **    ----------------------------------------------------------------------------
  407. */
  408.  
  409. static INT32 _Func4(void) {
  410.     asm    {
  411.         move.l    d0,-(sp)    /* move the arg "char* cStr" onto the stack */
  412.                                             /* NOTE: since its an INT32 we do a "move.l" */
  413.  
  414.         jsr        Func4                /* call the C function */
  415.  
  416.         add.l    #4,sp                /* clean up the stack: add sizeof(char *) to SP */
  417.         }
  418. }
  419.  
  420. INT32 Func4(char* cStr) {
  421.     INT32 environValue;    /* interrupt environment pointer */
  422.     INT32 returnValue;
  423.     
  424.     /* we're at interrupt level */
  425.     environValue = SetupInterruptEnv();
  426.  
  427.     returnValue = gFunc4Count++;    
  428.     gApp->Msg((unsigned char*)"\p==> Function4:  cStr = ");    
  429.     gApp->Msg((unsigned char*)CtoPstr(cStr));
  430.     gApp->NewLine();
  431.     gApp->NewLine();
  432.  
  433.     ExitInterruptEnv(environValue);
  434.     return(returnValue);
  435. }
  436.  
  437.  
  438.  
  439.  
  440.  
  441.  
  442. /*
  443. **    ----------------------------------------------------------------------------
  444. **    FUNCTION Func5() => INT32 : sample service routine
  445. **    ----------------------------------------------------------------------------
  446. **
  447. **    Purpose:
  448. **        Example of a service routine that accepts one P-string arg.  The return value is the number
  449. **        of times this routine has been executed (saved in the global gFunc5Count).
  450. **
  451. **    Usage:
  452. **        Since SoftTalk calls service routines with args in registers, we have some asm glue
  453. **        to transfer args onto the stack; we then execute a standard C function call.
  454. **        This asm glue routine is registered with SoftTalk, and will then be called by
  455. **        SoftTalk (at interrupt time) whenever a new session is requested.
  456. **
  457. **    ----------------------------------------------------------------------------
  458. **    Version        Date        Author        Description
  459. **    -------        ----        ------        -----------
  460. **    01a             8/17/89     MAC            First draft.
  461. **    ----------------------------------------------------------------------------
  462. */
  463.  
  464. static INT32 _Func5(void) {
  465.     asm    {
  466.         move.l    d0,-(sp)    /* move the arg "Str255 pStr" onto the stack */
  467.                                             /* NOTE: since its an INT32 we do a "move.l" */
  468.  
  469.         jsr        Func5                /* call the C function */
  470.  
  471.         add.l    #4,sp                /* clean up the stack: add sizeof(INT32) to SP */
  472.         }
  473. }
  474.  
  475. INT32 Func5(Str255 pStr) {
  476.     Str255 msg;                    /* message string */
  477.     INT32 environValue;    /* interrupt environment pointer */
  478.     INT32 returnValue;
  479.     
  480.     /* we're at interrupt level */
  481.     environValue = SetupInterruptEnv();
  482.  
  483.     returnValue = gFunc5Count++;    
  484.     gApp->Msg((unsigned char*)"\p==> Function5:  pStr = ");    
  485.     gApp->Msg(pStr);
  486.     gApp->NewLine();
  487.     gApp->NewLine();
  488.  
  489.     ExitInterruptEnv(environValue);
  490.     return(returnValue);
  491. }
  492.  
  493.  
  494.  
  495.  
  496.  
  497. /*
  498. **    ----------------------------------------------------------------------------
  499. **    FUNCTION STServerCreate() => void : create our server entity
  500. **    ----------------------------------------------------------------------------
  501. **
  502. **    Purpose:
  503. **        Creates a SoftTalk server entity by: initializing SoftTalk; opening a server,
  504. **        giving the server a name using STAlias(); registering the service routines using
  505. **        STRegister().
  506. **
  507. **    Usage:
  508. **        Call in order to create a server entity.
  509. **
  510. **    ----------------------------------------------------------------------------
  511. **    Version        Date        Author        Description
  512. **    -------        ----        ------        -----------
  513. **    01a             8/17/89     MAC            First draft.
  514. **    ----------------------------------------------------------------------------
  515. */
  516.  
  517. void STServerCreate(void) {
  518.     STServer myServer;    /* SoftTalk "magic cookie" for the server */
  519.     STResult err;                /* result code */
  520.     Str255 msg;                    /* message string */
  521.     BYTE* serverName;        /* string with my server's name */
  522.     BYTE* format;                /* format string for registering functions */
  523.     
  524.     
  525.     /* first stash my A5 into my code space so I can set up an interrupt environment */
  526.     SetMyRealA5();
  527.  
  528.     /* initialize SoftTalk */
  529.     err = STInitialize();
  530.     if (err != noErr) {
  531.         SysBeep(1);
  532.         gApp->Msg((unsigned char*)"\pCould not initialize SoftTalk. :-(");
  533.         return;
  534.         }
  535.     gApp->Msg((unsigned char*)"\pSuccessfully initialized SoftTalk! :-)");
  536.  
  537.     
  538.     /* open a server */
  539.     err = STOpenServer(&myServer, 0);
  540.     gApp->Msg((unsigned char*)"\pTried to open server.  Error Code: ");
  541.     NumToString(err,msg);
  542.     gApp->Msg(msg);
  543.     if (err < noErr) {
  544.         SysBeep(1);
  545.         gApp->Msg((unsigned char*)"\pCould not open server :-(.");
  546.         gApp->NewLine();
  547.         return;
  548.         }
  549.     gServerID = myServer;
  550.     gApp->Msg((unsigned char*)"\pSuccessfully opened server :-)! ServerID is:");
  551.     NumToString((long)myServer,msg);
  552.     gApp->Msg(msg);
  553.     gApp->NewLine();
  554.  
  555.  
  556.     /* alias the server */
  557.     serverName = (BYTE*)"\pMichael:Dude@*";
  558.     err = STAlias(myServer,serverName);
  559.     gApp->Msg((unsigned char*)"\pTried to alias server.  Error Code: ");
  560.     NumToString(err,msg);
  561.     gApp->Msg(msg);
  562.     if (err < noErr) {
  563.         SysBeep(1);
  564.         gApp->Msg((unsigned char*)"\pCould not alias server :-(.");
  565.         gApp->NewLine();
  566.         return;
  567.         }
  568.     gApp->Msg((unsigned char*)"\pSuccessfully aliased server :-)!");
  569.     gApp->NewLine();
  570.  
  571.  
  572.  
  573.     /* register the server's routines */
  574.     format = (BYTE*)"\pI";
  575.     err = STRegister(myServer,kAcceptSessionCode, _AcceptSession, kSystemTaskRank, format);
  576.     gApp->Msg((unsigned char*)"\pTried to register AcceptSession().  Error Code: ");
  577.     NumToString(err,msg);
  578.     gApp->Msg(msg);
  579.     if (err < noErr) {
  580.         SysBeep(1);
  581.         gApp->Msg((unsigned char*)"\pCould not register :-(.");
  582.         gApp->NewLine();
  583.         return;
  584.         }
  585.  
  586.  
  587.     format = (BYTE*)"";
  588.     err = STRegister(myServer,(UINT32)'F1', _Func1, kFunctionRank, format);
  589.     gApp->Msg((unsigned char*)"\pTried to register Function1().  Error Code: ");
  590.     NumToString(err,msg);
  591.     gApp->Msg(msg);
  592.     if (err < noErr) {
  593.         SysBeep(1);
  594.         gApp->Msg((unsigned char*)"\pCould not register :-(.");
  595.         gApp->NewLine();
  596.         return;
  597.         }
  598.  
  599.     format = (BYTE*)"4";
  600.     err = STRegister(myServer,(UINT32)'F2', _Func2, kFunctionRank, format);
  601.     gApp->Msg((unsigned char*)"\pTried to register Function2().  Error Code: ");
  602.     NumToString(err,msg);
  603.     gApp->Msg(msg);
  604.     if (err < noErr) {
  605.         SysBeep(1);
  606.         gApp->Msg((unsigned char*)"\pCould not register :-(.");
  607.         gApp->NewLine();
  608.         return;
  609.         }
  610.  
  611.     format = (BYTE*)"42";
  612.     err = STRegister(myServer,(UINT32)'F3', _Func3, kFunctionRank, format);
  613.     gApp->Msg((unsigned char*)"\pTried to register Function3().  Error Code: ");
  614.     NumToString(err,msg);
  615.     gApp->Msg(msg);
  616.     if (err < noErr) {
  617.         SysBeep(1);
  618.         gApp->Msg((unsigned char*)"\pCould not register :-(.");
  619.         gApp->NewLine();
  620.         return;
  621.         }
  622.  
  623.     format = (BYTE*)"C";
  624.     err = STRegister(myServer,(UINT32)'F4', _Func4, kFunctionRank, format);
  625.     gApp->Msg((unsigned char*)"\pTried to register Function4().  Error Code: ");
  626.     NumToString(err,msg);
  627.     gApp->Msg(msg);
  628.     if (err < noErr) {
  629.         SysBeep(1);
  630.         gApp->Msg((unsigned char*)"\pCould not register :-(.");
  631.         gApp->NewLine();
  632.         return;
  633.         }
  634.  
  635.     format = (BYTE*)"P";
  636.     err = STRegister(myServer,(UINT32)'F5', _Func5, kFunctionRank, format);
  637.     gApp->Msg((unsigned char*)"\pTried to register Function5().  Error Code: ");
  638.     NumToString(err,msg);
  639.     gApp->Msg(msg);
  640.     if (err < noErr) {
  641.         SysBeep(1);
  642.         gApp->Msg((unsigned char*)"\pCould not register :-(.");
  643.         gApp->NewLine();
  644.         return;
  645.         }
  646.  
  647.     gApp->Msg((unsigned char*)"\pSuccessfully registered service routines :-)!");
  648.     gApp->NewLine();
  649. }
  650.  
  651.  
  652.  
  653.  
  654.  
  655.  
  656.  
  657.  
  658. /*
  659. **    ----------------------------------------------------------------------------
  660. **    FUNCTION STServerDispose() => void : close down the server entity
  661. **    ----------------------------------------------------------------------------
  662. **
  663. **    Purpose:
  664. **        Close down a server that has been previously created.
  665. **
  666. **    Usage:
  667. **        After you're done with the server, simply call this routine to close down the
  668. **        connection to SoftTalk.
  669. **
  670. **    ----------------------------------------------------------------------------
  671. **    Version        Date        Author        Description
  672. **    -------        ----        ------        -----------
  673. **    01a             8/17/89     MAC            First draft.
  674. **    ----------------------------------------------------------------------------
  675. */
  676.  
  677. void STServerDispose(void) {    
  678.     STResult err;                /* result code */
  679.     Str255 msg;                    /* message string */
  680.     
  681.     /* close the server */
  682.     err = STCloseServer(gServerID);
  683.     gApp->Msg((unsigned char*)"\pDispose: Tried to close server.  Error Code =");
  684.     NumToString(err,msg);
  685.     gApp->Msg(msg);
  686.     if (err < noErr) {
  687.         SysBeep(1);
  688.         gApp->Msg((unsigned char*)"\pDispose: Could not close server :-(.  Error Code =");
  689.         gApp->NewLine();
  690.         return;
  691.         }
  692.     gApp->Msg((unsigned char*)"\pDispose: Successfully closed server :-)!");
  693.     gApp->NewLine();
  694.     gServerID = 0;
  695. }
  696.  
  697.  
  698.  
  699.  
  700.  
  701.  
  702.  
  703.  
  704. /*
  705. **    ----------------------------------------------------------------------------
  706. **    FUNCTION STServerTrigger() => void : tell SoftTalk if we're ready to accept calls
  707. **    ----------------------------------------------------------------------------
  708. **
  709. **    Purpose:
  710. **        This routine should be called as often as possible from the outside, so that the
  711. **        server has a chance to tell SoftTalk when it is able to accept calls to its service
  712. **        routines.  Currently the mechanism that SoftTalk provides for this purpose, STHear(),
  713. **        is not sophisticated enough to allow for accurate server control.
  714. **
  715. **    Usage:
  716. **        Call from the main-event-loop on every pass.
  717. **
  718. **    ----------------------------------------------------------------------------
  719. **    Version        Date        Author        Description
  720. **    -------        ----        ------        -----------
  721. **    01a             8/17/89     MAC            First draft.
  722. **    ----------------------------------------------------------------------------
  723. */
  724.  
  725. void STServerTrigger(void) {
  726.     STResult result;
  727.     
  728.     /* if our server has been initialized, then continously call STHear() until all
  729.          pending requests have been serviced.  We call with kFunctionRank that all
  730.          routines with priority higher or equal to this will be serviced */
  731.     if (gServerID != 0) {
  732.         while ( (BOOLEAN)STHear(gServerID, kFunctionRank) )
  733.             ;
  734.         }
  735. }
  736.